package com.asgard.crypto;

import com.asgard.utils.CryptoUtils;
import org.bouncycastle.util.encoders.Hex;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;

/**
 * 该类封装了一个公钥/私钥密钥对，或者在没有私钥的情况下只有公钥本身。
 */
public class ECKey {

    /**
     * 私钥
     */
    private final PrivateKey privKey;
    /**
     * 公钥
     */
    private final PublicKey pubKey;
    /**
     * 缓存公钥字节数组
     */
    private byte[] pubKeyBytes = null;

    /**
     * 构造函数，通过私钥和公钥构造。
     *
     * @param priv 私钥
     * @param pub  公钥
     */
    public ECKey(PrivateKey priv, PublicKey pub) {
        this.privKey = priv;
        this.pubKey = pub;
    }

    /**
     * 构造函数，通过公钥构造。
     *
     * @param pub 公钥
     */
    public ECKey(PublicKey pub) {
        this(null, pub);
    }

    /**
     * 是否只有公钥。
     *
     * @return 是否只有公钥
     */
    public boolean isPubKeyOnly() {
        return privKey == null;
    }

    /**
     * 是否有私钥。
     *
     * @return 是否有私钥
     */
    public boolean hasPrivKey() {
        return privKey != null;
    }

    /**
     * 返回私钥。
     *
     * @return 私钥
     */
    public PrivateKey getPrivateKey() {
        return privKey;
    }

    /**
     * 返回公钥。
     *
     * @return 公钥
     */
    public PublicKey getPublicKey() {
        return pubKey;
    }

    /**
     * 以字节数组形式返回公钥。
     *
     * @return 公钥
     */
    public byte[] getPubKey() {
        if (this.pubKeyBytes != null)
            return this.pubKeyBytes;
        this.pubKeyBytes = CryptoUtils.getECPublicKeyCompressedBytes(pubKey);
        return this.pubKeyBytes;
    }

    /**
     * 获取私钥对应的字节数组。
     *
     * @return 私钥对应的字节数组
     */
    public byte[] getPrivKeyBytes() {
        return CryptoUtils.getECPrivateKeyBytes(privKey);
    }

    /**
     * 返回Hex格式的私钥。
     *
     * @return Hex格式的私钥
     */
    public String getPrivateKeyAsHex() {
        return Hex.toHexString(getPrivKeyBytes());
    }

    /**
     * 返回Hex格式的公钥。
     *
     * @return Hex格式的公钥
     */
    public String getPublicKeyAsHex() {
        return Hex.toHexString(getPubKey());
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(pubKeyBytes);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ECKey other = (ECKey) obj;
        if (!Arrays.equals(pubKeyBytes, other.pubKeyBytes))
            return false;
        if (hasPrivKey() != other.hasPrivKey())
            return false;
        return true;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Begin ECKey\n");
        sb.append("PublicKey: ").append(getPublicKeyAsHex()).append("\n");
        if (hasPrivKey())
            sb.append("PrivateKey: ").append(getPrivateKeyAsHex()).append("\n");
        sb.append("End ECKey");
        return sb.toString();
    }
}
